package cn.zwx.activiti.example.common.aspect;

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


/**
 * @description 系统日志，切面处理
 * @author zhangwenxue
 * @createTime 2020/10/26 16:29
 **/
@Aspect
@Component
public class SysLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(SysLogAspect.class);

	@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
	public void logPointCut() {

	}

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(attributes)){
            //异步方法单独处理
            logger.info("异步方法统计不了接口时长,直接跳过...");
            Object result = point.proceed();
            return result;
        }
        HttpServletRequest request = attributes.getRequest();
        //排除上传打印
        if (request.getRequestURI().contains("uploadFile")) {
            logger.info("请求url={}, 文件上传未打印参数", request.getRequestURI());
        } else {
            List<Object> logArgs = Arrays.stream(point.getArgs())
                    .filter(arg -> (!(arg instanceof HttpServletRequest) && !(arg instanceof HttpServletResponse)))
                    .collect(Collectors.toList());
            try {
                logger.info("请求url={}, 请求参数={}", request.getRequestURI(), JSON.toJSONString(logArgs));
            } catch (Exception e) {
                logger.error("请求参数获取异常", e);
            }
        }
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        try {
            logger.info("请求耗时={}ms, 返回结果={}", time, JSON.toJSONString(result));
        } catch (Exception e) {
            logger.error("返回参数获取异常", e);
        }

        return result;
    }



}
